package com.zjinyin.forum.common;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: DELL
 * Date: 2023-08-09
 * Time: 9:18
 */

import com.fasterxml.jackson.annotation.JsonInclude;

/**
 * 统一的返回数据类型
 * 结构 : ResultAjax <T>
 * 泛型在编译的时候会被擦除成为一个 Object 类
 */

public class AppResult<T> {

    /**
     * 由于配置文件中将所有返回的 JSON 字符串为 null 的值都给去除了,
     * 但当成功返回时, 不一定会有 data 信息返回.
     * 为了保持返回格式的同意, 需要让 AppResult 的字段全部强制序列化
     */

    // 状态码
    @JsonInclude(JsonInclude.Include.ALWAYS)
    private int code;

    // 信息描述
    @JsonInclude(JsonInclude.Include.ALWAYS)
    private String message;

    // 返回数据
    @JsonInclude(JsonInclude.Include.ALWAYS)
    private T data;

    /**
     * 成功方法 - 无数据返回
     *
     * @return 只返回成功状态码和对应描述信息
     */
    public static AppResult success() {
        return new AppResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage());
    }

    /**
     * 成功方法 - 无信息返回, 同时返回自定义的描述信息
     *
     * @param message 自定义描述信息
     * @return 返回成功状态码和自定义描述信息
     */
    public static AppResult success(String message) {
        return new AppResult(ResultCode.SUCCESS.getCode(), message);
    }

    /**
     * <T> AppResult <T> success (T data)
     *
     * <T> : 作为方法的参数类型, 表示这个方法是一个泛型方法, 通过 <T> 可以在方法内部使用泛型类型, 并可以根据具体类型参数来确定返回值
     *
     * AppResult <T> : 表示返回一个 AppResult 对象, 其中的 T 表示具体的数据类型.
     *                 这里的 T 与方法的类型参数 <T> 相对应，表示返回的 AppResult 对象中的数据类型与传入的类型参数相同
     *
     * T data : 作为方法的参数, 其类型为泛型类型参数 T
     *          在方法调用时，可以传入任意类型的 data 参数，并根据实际传入的参数类型来确定泛型类型参数 T 所代表的具体类型
     */

    /**
     * 成功方法 - 返回自定义数据
     *
     * @param data 自定义数据
     * @param <T>  泛型参数
     * @return 返回成功状态码和对应描述信息以及泛型的自定义数据
     */
    public static <T> AppResult<T> success(T data) {
        return new AppResult<>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data);
    }

    /**
     * 成功方法 - 返回自定义的描述信息和数据
     *
     * @param message 自定义描述信息
     * @param data    自定义的泛型数据
     * @param <T>     参数为泛型
     * @return 返回成功状态码和自定义的信息描述以及数据
     */
    public static <T> AppResult<T> success(String message, T data) {
        return new AppResult<>(ResultCode.SUCCESS.getCode(), message, data);
    }


    /**
     * 错误方法 - 无数据返回
     *
     * @return 返回错误的状态码和信息
     */
    public static AppResult failed() {
        return new AppResult(ResultCode.FAILED.getCode(), ResultCode.FAILED.getMessage());
    }

    /**
     * 错误方法 - 无数据返回, 并且返回自定义信息
     *
     * @param message 自定义错误信息
     * @return 返回状态码和对应自定义信息
     */
    public static AppResult failed(String message) {
        return new AppResult(ResultCode.FAILED.getCode(), message);
    }

    /**
     * 错误方法 - 构造自定义的返回对象 ( 自定义的状态码和对应信息 )
     *
     * @param resultCode 自定义的返回对象
     * @return 返回自定义的构造对象的状态码和描述信息
     */
    public static AppResult failed(ResultCode resultCode) {
        return new AppResult(resultCode.getCode(), resultCode.getMessage());
    }


    /**
     * 构造方法, 只传入状态码和描述信息, 无数据返回
     *
     * @param code    状态码
     * @param message 信息描述
     */
    public AppResult(int code, String message) {
        // 调用三个参数的构造方法, data 传入 null
        this(code, message, null);
    }

    /**
     * 构造方法 - 传入状态码, 信息描述和数据返回
     *
     * @param code    状态码
     * @param message 信息 描述
     * @param data    返回数
     */
    public AppResult(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}
